/*
 * GraphWindow.java
 *
 * @author Giuliano Vilela
 */

package graphxt.gui;

import graphxt.model.Edge;
import graphxt.model.Graph;
import graphxt.model.Vertex;
import graphxt.plugins.BFSPlugin;
import graphxt.plugins.DFSPlugin;
import graphxt.plugins.DijkstraPlugin;
import graphxt.plugins.FordFulkersonPlugin;
import graphxt.plugins.KruskalPlugin;
import graphxt.plugins.PrimPlugin;
import graphxt.plugins.TopologicalSortPlugin;
import graphxt.view.EdgeView;
import graphxt.view.GraphTheme;
import graphxt.view.GraphView;
import graphxt.view.VertexView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * GraphWindow
 * 
 * Classe Swing principal da aplicação. Representa
 * as janelas internas do software, que guardam e gerenciam
 * a iteração do usuário com um grafo qualquer.
 * 
 * @author Giuliano Vilela
 */
public class GraphWindow extends javax.swing.JInternalFrame {
    
    /**
     * Creates new form GraphWindow
     */
    public GraphWindow() {
        initComponents();
        initGraph();
        initButtons();
        initMouseEvent();
        initPluginSection();
        setTitle("Untitled");
        file_ch = new JFileChooser();

        clearButton.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent ae) {
            graph_view.deselectAll();
            for (EdgeView<String,Integer> e : graph_view.getEdgeViewSet())
              e.setEdgeInfo(null);
            graph_view.repaint();
          }
        });
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    buttonGroup1 = new javax.swing.ButtonGroup();
    jScrollPane1 = new javax.swing.JScrollPane();
    jTabbedPane1 = new javax.swing.JTabbedPane();
    jPanel1 = new javax.swing.JPanel();
    jPanel6 = new javax.swing.JPanel();
    selVeEdButton = new javax.swing.JToggleButton();
    selVeButton = new javax.swing.JToggleButton();
    selEdButton = new javax.swing.JToggleButton();
    jPanel7 = new javax.swing.JPanel();
    jPanel2 = new javax.swing.JPanel();
    adVeButton = new javax.swing.JToggleButton();
    adEdButton = new javax.swing.JToggleButton();
    jPanel9 = new javax.swing.JPanel();
    reVeButton = new javax.swing.JToggleButton();
    reEdButton = new javax.swing.JToggleButton();
    jPanel10 = new javax.swing.JPanel();
    lbVeButton = new javax.swing.JToggleButton();
    lbEdButton = new javax.swing.JToggleButton();
    clearButton = new javax.swing.JButton();
    jTabbedPane2 = new javax.swing.JTabbedPane();
    jPanel4 = new javax.swing.JPanel();
    jPanel3 = new javax.swing.JPanel();
    bfsOpt = new javax.swing.JRadioButton();
    dfsOpt = new javax.swing.JRadioButton();
    topOpt = new javax.swing.JRadioButton();
    dijOpt = new javax.swing.JRadioButton();
    kruskalOpt = new javax.swing.JRadioButton();
    primOpt = new javax.swing.JRadioButton();
    fordFulkerson = new javax.swing.JRadioButton();
    jPanel5 = new javax.swing.JPanel();
    jButton1 = new javax.swing.JButton();
    jButton4 = new javax.swing.JButton();
    jLabel1 = new javax.swing.JLabel();
    speedSlider = new javax.swing.JSlider();
    jPanel8 = new javax.swing.JPanel();
    jScrollPane2 = new javax.swing.JScrollPane();
    messageBoard = new javax.swing.JList();
    jToolBar1 = new javax.swing.JToolBar();
    jButton6 = new javax.swing.JButton();
    jSeparator1 = new javax.swing.JToolBar.Separator();
    jButton5 = new javax.swing.JButton();
    jSeparator2 = new javax.swing.JToolBar.Separator();
    jButton2 = new javax.swing.JButton();
    jSeparator3 = new javax.swing.JToolBar.Separator();
    jButton3 = new javax.swing.JButton();

    setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEtchedBorder(), javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED)));
    setClosable(true);
    setIconifiable(true);
    setMaximizable(true);
    setResizable(true);
    setTitle("Untitled");
    setDoubleBuffered(true);
    setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    addInternalFrameListener(new javax.swing.event.InternalFrameListener() {
      public void internalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
      }
      public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt) {
        formInternalFrameClosed(evt);
      }
      public void internalFrameClosing(javax.swing.event.InternalFrameEvent evt) {
      }
      public void internalFrameDeactivated(javax.swing.event.InternalFrameEvent evt) {
      }
      public void internalFrameDeiconified(javax.swing.event.InternalFrameEvent evt) {
      }
      public void internalFrameIconified(javax.swing.event.InternalFrameEvent evt) {
      }
      public void internalFrameOpened(javax.swing.event.InternalFrameEvent evt) {
      }
    });

    jScrollPane1.setBackground(new java.awt.Color(85, 85, 85));
    jScrollPane1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 2, true));
    jScrollPane1.setDoubleBuffered(true);
    jScrollPane1.setFont(new java.awt.Font("DejaVu Sans", 0, 11));

    jTabbedPane1.setFont(new java.awt.Font("DejaVu Sans", 0, 11));

    jPanel6.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Select", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    selVeEdButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    selVeEdButton.setText("Vertex & Edges");
    selVeEdButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    selVeButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    selVeButton.setText("Vertex");
    selVeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    selEdButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    selEdButton.setText("Edge");
    selEdButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
    jPanel6.setLayout(jPanel6Layout);
    jPanel6Layout.setHorizontalGroup(
      jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel6Layout.createSequentialGroup()
        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(jPanel6Layout.createSequentialGroup()
            .addComponent(selVeButton)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(selEdButton))
          .addComponent(selVeEdButton, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE))
        .addContainerGap())
    );

    jPanel6Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {selEdButton, selVeButton});

    jPanel6Layout.setVerticalGroup(
      jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel6Layout.createSequentialGroup()
        .addComponent(selVeEdButton)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(selVeButton)
          .addComponent(selEdButton))
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Elements", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Add", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    adVeButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    adVeButton.setText("Vertex");
    adVeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    adEdButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    adEdButton.setText("Edge");
    adEdButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
    jPanel2.setLayout(jPanel2Layout);
    jPanel2Layout.setHorizontalGroup(
      jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel2Layout.createSequentialGroup()
        .addComponent(adVeButton)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
        .addComponent(adEdButton)
        .addGap(30, 30, 30))
    );

    jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {adEdButton, adVeButton});

    jPanel2Layout.setVerticalGroup(
      jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel2Layout.createSequentialGroup()
        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(adVeButton)
          .addComponent(adEdButton))
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    jPanel9.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Remove", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    reVeButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    reVeButton.setText("Vertex");
    reVeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    reEdButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    reEdButton.setText("Edge");
    reEdButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9);
    jPanel9.setLayout(jPanel9Layout);
    jPanel9Layout.setHorizontalGroup(
      jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel9Layout.createSequentialGroup()
        .addComponent(reVeButton)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
        .addComponent(reEdButton))
    );

    jPanel9Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {reEdButton, reVeButton});

    jPanel9Layout.setVerticalGroup(
      jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel9Layout.createSequentialGroup()
        .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(reVeButton)
          .addComponent(reEdButton))
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    jPanel10.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Relabel", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    lbVeButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    lbVeButton.setText("Vertex");
    lbVeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    lbEdButton.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    lbEdButton.setText("Edge");
    lbEdButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        selVeEdButtonActionPerformed(evt);
      }
    });

    javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10);
    jPanel10.setLayout(jPanel10Layout);
    jPanel10Layout.setHorizontalGroup(
      jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel10Layout.createSequentialGroup()
        .addComponent(lbVeButton)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
        .addComponent(lbEdButton))
    );

    jPanel10Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {lbEdButton, lbVeButton});

    jPanel10Layout.setVerticalGroup(
      jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel10Layout.createSequentialGroup()
        .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(lbVeButton)
          .addComponent(lbEdButton))
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
    jPanel7.setLayout(jPanel7Layout);
    jPanel7Layout.setHorizontalGroup(
      jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel7Layout.createSequentialGroup()
        .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
          .addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addContainerGap())
    );
    jPanel7Layout.setVerticalGroup(
      jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel7Layout.createSequentialGroup()
        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    clearButton.setText("Clear");

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
          .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(clearButton)))
        .addContainerGap())
    );
    jPanel1Layout.setVerticalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(clearButton)
        .addContainerGap(73, Short.MAX_VALUE))
    );

    jTabbedPane1.addTab("Control", jPanel1);

    jTabbedPane2.setFont(new java.awt.Font("DejaVu Sans", 0, 11));

    jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Algorithms", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    buttonGroup1.add(bfsOpt);
    bfsOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    bfsOpt.setText("Breadth-First Search");

    buttonGroup1.add(dfsOpt);
    dfsOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    dfsOpt.setText("Depth-First Search");

    buttonGroup1.add(topOpt);
    topOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    topOpt.setText("Topological Sort");

    buttonGroup1.add(dijOpt);
    dijOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    dijOpt.setText("Dijkstra Shortest Path");

    buttonGroup1.add(kruskalOpt);
    kruskalOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    kruskalOpt.setText("Kruskal - MST");

    buttonGroup1.add(primOpt);
    primOpt.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    primOpt.setText("Prim-Jarnik - MST");

    fordFulkerson.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    fordFulkerson.setText("Ford-Fukerson - MaxFlow");

    javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
    jPanel3.setLayout(jPanel3Layout);
    jPanel3Layout.setHorizontalGroup(
      jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel3Layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
            .addComponent(bfsOpt, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
            .addContainerGap())
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
            .addComponent(dfsOpt, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
            .addContainerGap())
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
            .addComponent(topOpt, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
            .addContainerGap())
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
            .addComponent(dijOpt, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
            .addContainerGap())
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
            .addComponent(kruskalOpt, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
            .addContainerGap())
          .addComponent(primOpt, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
          .addGroup(jPanel3Layout.createSequentialGroup()
            .addComponent(fordFulkerson)
            .addContainerGap(32, Short.MAX_VALUE))))
    );
    jPanel3Layout.setVerticalGroup(
      jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel3Layout.createSequentialGroup()
        .addComponent(bfsOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(dfsOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(topOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(dijOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(kruskalOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(primOpt)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(fordFulkerson))
    );

    jPanel3Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bfsOpt, dfsOpt, dijOpt, kruskalOpt, primOpt, topOpt});

    jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Control", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    jButton1.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton1.setText("Start");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton1ActionPerformed(evt);
      }
    });

    jButton4.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton4.setText("Stop");
    jButton4.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton4ActionPerformed(evt);
      }
    });

    jLabel1.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jLabel1.setText("Speed (s):");

    speedSlider.setMajorTickSpacing(2);
    speedSlider.setMaximum(7);
    speedSlider.setMinimum(1);
    speedSlider.setMinorTickSpacing(1);
    speedSlider.setValue(6);

    javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
    jPanel5.setLayout(jPanel5Layout);
    jPanel5Layout.setHorizontalGroup(
      jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel5Layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(jPanel5Layout.createSequentialGroup()
            .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(41, 41, 41)
            .addComponent(jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, 67, Short.MAX_VALUE))
          .addGroup(jPanel5Layout.createSequentialGroup()
            .addComponent(jLabel1)
            .addGap(2, 2, 2)
            .addComponent(speedSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 114, Short.MAX_VALUE)))
        .addContainerGap())
    );

    jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jButton1, jButton4});

    jPanel5Layout.setVerticalGroup(
      jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel5Layout.createSequentialGroup()
        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jButton1)
          .addComponent(jButton4))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jLabel1)
          .addComponent(speedSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
    );

    jPanel5Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {jButton1, jButton4});

    jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Messages", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("DejaVu Sans", 0, 11))); // NOI18N

    messageBoard.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 2, true));
    messageBoard.setFont(new java.awt.Font("DejaVu Sans", 0, 10));
    messageBoard.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
    messageBoard.setDoubleBuffered(true);
    jScrollPane2.setViewportView(messageBoard);

    javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
    jPanel8.setLayout(jPanel8Layout);
    jPanel8Layout.setHorizontalGroup(
      jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 203, Short.MAX_VALUE)
    );
    jPanel8Layout.setVerticalGroup(
      jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
    );

    javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
    jPanel4.setLayout(jPanel4Layout);
    jPanel4Layout.setHorizontalGroup(
      jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
      .addGroup(jPanel4Layout.createSequentialGroup()
        .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE)
        .addContainerGap())
      .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );
    jPanel4Layout.setVerticalGroup(
      jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel4Layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    jTabbedPane2.addTab("Plugins", jPanel4);

    jToolBar1.setRollover(true);

    jButton6.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton6.setIcon(new javax.swing.ImageIcon(getClass().getResource("/graphxt/images/2folder-new.png"))); // NOI18N
    jButton6.setToolTipText("New Graph");
    jButton6.setMargin(new java.awt.Insets(0, 0, 0, 0));
    jButton6.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton6ActionPerformed(evt);
      }
    });
    jToolBar1.add(jButton6);
    jToolBar1.add(jSeparator1);

    jButton5.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/graphxt/images/2document-open.png"))); // NOI18N
    jButton5.setToolTipText("Open a new Graph");
    jButton5.setMargin(new java.awt.Insets(0, 0, 0, 0));
    jButton5.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton5ActionPerformed(evt);
      }
    });
    jToolBar1.add(jButton5);
    jToolBar1.add(jSeparator2);

    jButton2.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/graphxt/images/2document-save.png"))); // NOI18N
    jButton2.setToolTipText("Save");
    jButton2.setMargin(new java.awt.Insets(0, 0, 0, 0));
    jButton2.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton2ActionPerformed(evt);
      }
    });
    jToolBar1.add(jButton2);
    jToolBar1.add(jSeparator3);

    jButton3.setFont(new java.awt.Font("DejaVu Sans", 0, 11));
    jButton3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/graphxt/images/2document-save-as.png"))); // NOI18N
    jButton3.setToolTipText("Save as");
    jButton3.setMargin(new java.awt.Insets(0, 0, 0, 0));
    jButton3.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton3ActionPerformed(evt);
      }
    });
    jToolBar1.add(jButton3);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 433, Short.MAX_VALUE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jTabbedPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap())
      .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 851, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
          .addComponent(jTabbedPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
          .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
          .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE))
        .addContainerGap())
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents

    private void formInternalFrameClosed(javax.swing.event.InternalFrameEvent evt) {//GEN-FIRST:event_formInternalFrameClosed
        close();
    }//GEN-LAST:event_formInternalFrameClosed

    /**
     * Faz com que,ao momento que um toggleButton
     * seja ativado, todos os outros relacionados com
     * ele sejam desativados.
     */
    private void selVeEdButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selVeEdButtonActionPerformed
        for (JToggleButton b : toggle_buttons)
            if (b != (JToggleButton)evt.getSource())
                b.setSelected(false);
}//GEN-LAST:event_selVeEdButtonActionPerformed

    /**
     * Responde ao botão start.
     * Cria uma nova instância de plugin, de acordo
     * com a seleção do usuário, e registra-o como ActionListener
     * de um timer interno desta janela.
     */
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        stopPlugins();
        timer.setDelay((8 - speedSlider.getValue())*1000);
        
        if (bfsOpt.isSelected()) {
            String inf = JOptionPane.showInputDialog("What's the initial vertex?");
            
            timer.addActionListener(new BFSPlugin(
                graph_view.getGraph().getVertex(inf),
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();
        }
        else if (dfsOpt.isSelected()) {
            String inf = JOptionPane.showInputDialog("What's the initial vertex?");
            
            timer.addActionListener(new DFSPlugin(
                graph_view.getGraph().getVertex(inf),
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();   
        }
        else if (dijOpt.isSelected()) {
            String inf = JOptionPane.showInputDialog("What's the initial vertex?");
            
            timer.addActionListener(new DijkstraPlugin(
                graph_view.getGraph().getVertex(inf),
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();           
        }
        else if (kruskalOpt.isSelected()) {
            timer.addActionListener(new KruskalPlugin(
                null,
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();           
        }
        else if (primOpt.isSelected()) {
            String inf = JOptionPane.showInputDialog("What's the first vertex in the tree?");
            
            timer.addActionListener(new PrimPlugin(
                graph_view.getGraph().getVertex(inf),
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();                       
        }
        else if (topOpt.isSelected()) {
            timer.addActionListener(new TopologicalSortPlugin(
                null,
                graph_view.getGraph(),
                graph_view,this,timer
            ));
            
            timer.start();                                   
        }
        else if (fordFulkerson.isSelected()) {
          String src = JOptionPane.showInputDialog("What's the source vertex?");
          String dest = JOptionPane.showInputDialog("What's the destiny vertex?");
          String search = JOptionPane.showInputDialog("What's the search type ? (DFS/BFS)");

          Vertex<String> s = new Vertex<String>(src);
          Vertex<String> t = new Vertex<String>(dest);
          int searchType = search.equalsIgnoreCase("DFS") ?
            FordFulkersonPlugin.DFS_PATH : FordFulkersonPlugin.BFS_PATH;

          timer.addActionListener(new FordFulkersonPlugin(
            searchType, s, t,
            graph_view.getGraph(),
            graph_view, this, timer
          ));

          timer.start();
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        stopPlugins();
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed
        stopPlugins();
        initGraph();
        setTitle("Untitled");
        repaint();
    }//GEN-LAST:event_jButton6ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        try {
            saveFile();//GEN-LAST:event_jButton2ActionPerformed
        } catch (Exception ex) {
            Logger.getLogger(GraphWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        try {
            saveAs();//GEN-LAST:event_jButton3ActionPerformed
        } catch (Exception ex) {
            Logger.getLogger(GraphWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        try {
            openFile();//GEN-LAST:event_jButton5ActionPerformed
        } catch (Exception ex) {
            Logger.getLogger(GraphWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Interrompe a execução de todos os plugins
     * que estão rodando no momento.
     */
    private void stopPlugins() {
        timer.stop();
        ActionListener[] jobs = timer.getActionListeners();
        
        if (jobs == null) return;

        for (ActionListener al : jobs) {
            timer.removeActionListener(al);
        }
    }
    
    /**
     * Inicializa a janela com um novo grafo vazio.
     */
    private void initGraph() {
        theme = GraphTheme.Default;
        
        Graph<String,Integer> graph = new Graph<String,Integer>();
        graph_view = new GraphView(graph,theme);
        
        graph_view.setSize(jScrollPane1.getWidth(),jScrollPane1.getHeight());
        graph_view.setLocation(0,0);
        graph_view.setGraph(graph);
        jScrollPane1.setViewportView(graph_view);
        pack();
    }
    
    /**
     * Inicializa os componentes que compôem a seção dos plugins.
     */
    private void initPluginSection() {
        messageBoard.setBackground(theme.getBackgroundColor());
        messageBoard.setForeground(theme.getEdgeColor());
        messageBoard.setSelectionBackground(theme.getSelectedVertexFillColor());
        messageBoard.setSelectionForeground(theme.getSelectedEdgeColor());
        
        messages = new DefaultListModel();
        messageBoard.setModel(messages);
        
        timer = new Timer((8 - speedSlider.getValue())*1000,null);
        
        postMessage("Plugin section initialized.");
    }
    
    /**
     * Posta uma mensagem no Message Board desta janela,
     * obedecendo o limite imposto internamente de ter
     * sempre somente 50 mensagens sendo exibidas ao usuário.
     */
    public void postMessage(String str) {
        if (messages.getSize() == 50) {
            messages.remove(0);
        }
        
        messages.addElement(str);    
        messageBoard.ensureIndexIsVisible(messages.getSize()-1);
    }
    
    /**
     * Coloca os toggleButtons em um mesmo grupo, para
     * controle interno.
     */
    private void initButtons() {
        toggle_buttons = new ArrayList<JToggleButton>(15);
        toggle_buttons.add(selVeEdButton);
        toggle_buttons.add(selVeButton);
        toggle_buttons.add(selEdButton);
        toggle_buttons.add(adVeButton);
        toggle_buttons.add(reVeButton);
        toggle_buttons.add(adEdButton);
        toggle_buttons.add(reEdButton);
        toggle_buttons.add(lbVeButton);
        toggle_buttons.add(lbEdButton);
    }
    
    /**
     * Conecta todos os eventos de mouse relacionados ao
     * GraphView desta janela com os seus respectivos eventos
     * de handling.
     */
    private void initMouseEvent() {
        final GraphWindow window = this;
        graph_view.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                graph_view.mouseClicked(evt,toggle_buttons,window);
            }
        });
        
        graph_view.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mousePressed(java.awt.event.MouseEvent evt) {
                graph_view.mousePressed(evt);
            }
        });

        graph_view.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                graph_view.mouseReleased();
            }
        });
        graph_view.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
           @Override
           public void mouseMoved(java.awt.event.MouseEvent evt) {
               graph_view.mouseMoved(evt);
           }
        });
        graph_view.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
           @Override
           public void mouseDragged(java.awt.event.MouseEvent evt) {
               graph_view.mouseDragged(evt);
           }
        });
    }
    
    /**
     * Fecha a janela.
     */
    public void close() {
        setVisible(false);
    }
    
    /**
     * Implementa a ação "Salvar como".
     * @throws java.lang.Exception
     */
    public void saveAs() throws Exception {
        if (file_ch.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
            return;

        saveFile(file_ch.getSelectedFile());

        setTitle(file_ch.getSelectedFile().getCanonicalPath());

        repaint();
    }

    /**
     * Implementa a ação "Salvar".
     * @throws java.lang.Exception
     */
    public void saveFile() throws Exception {
        String name = getTitle();
        if (name.startsWith("Untitled"))
            saveAs();
        else
            saveFile(new File(name));
    }

    /**
     * Método interno utilizado para salvar
     * o grafo atual no arquivo representado
     * por f.
     * @throws java.lang.Exception
     */
    private void saveFile(File f) throws Exception {
        RandomAccessFile file = null;

        try {
            file = new RandomAccessFile(f, "rw");
            file.setLength(1);
            file.writeBytes(getXMLGraph());
        }
        catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(
                    this, "Arquivo inexistente ou permissão negada\n" + ex.getMessage(),
                    "GraphXT [Erro]", JOptionPane.ERROR_MESSAGE
            );                
        }
        catch (java.io.IOException ex) {
            JOptionPane.showMessageDialog(
                this, "Erro ao escrever no arquivo\n" + ex.getMessage(),
                "GraphXT [Erro]", JOptionPane.ERROR_MESSAGE
            );
        }

        try {
            if (file != null) file.close();
        } catch (java.io.IOException ex) { }
        
        postMessage("File " + f.getName() + " saved.");
    }
    
    /**
     * Implementa a ação "Abrir".
     * @throws java.lang.Exception
     */
    public void openFile() throws Exception {
        jButton6ActionPerformed(null);
        
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        
        if (file_ch.showOpenDialog(this) != JFileChooser.APPROVE_OPTION)
            return;
        
        Document doc = db.parse(file_ch.getSelectedFile());
        
        Node graph = doc.getElementsByTagName("graph").item(0);
        NodeList elements = graph.getChildNodes();
        
        for (int i = 0; i < elements.getLength(); ++i) {
            Node el = elements.item(i);
            NamedNodeMap attr = el.getAttributes();
            
            if (el.getNodeName().equals("vertex")) {
                String data = attr.getNamedItem("data").getNodeValue();
                double x = Double.parseDouble(attr.getNamedItem("x").getNodeValue());
                double y = Double.parseDouble(attr.getNamedItem("y").getNodeValue());
                boolean sel = attr.getNamedItem("selected").getNodeValue().equals("1");
                
                graph_view.addVertex(x,y,data);
                graph_view.getVertexView(graph_view.getGraph().getVertex(data)).setSelected(sel);
            }
        }
        
        for (int i = 0; i < elements.getLength(); ++i) {
            Node el = elements.item(i);
            NamedNodeMap attr = el.getAttributes();
            
            if (el.getNodeName().equals("edge")) {
                String st = attr.getNamedItem("start").getNodeValue();
                String nd = attr.getNamedItem("end").getNodeValue();
                int data = Integer.valueOf(attr.getNamedItem("data").getNodeValue());
                double ctr_x = Double.parseDouble(attr.getNamedItem("control_x").getNodeValue());
                double ctr_y = Double.parseDouble(attr.getNamedItem("control_y").getNodeValue());
                boolean sel = attr.getNamedItem("selected").getNodeValue().equals("1");
                boolean dir = attr.getNamedItem("directed").getNodeValue().equals("1");

                Edge<String,Integer> edge = new Edge<String,Integer>(new Vertex<String>(st),new Vertex<String>(nd),dir,data);
                Edge<String,Integer> ed = null;
                
                graph_view.addEdge(st, nd, dir, data);
                
                for (Edge<String,Integer> e : graph_view.getGraph().getEdgeSet())
                    if (e.equals(edge)) {
                        ed = e;
                        break;
                    }
                
                graph_view.getEdgeView(ed).setSelected(sel);
                graph_view.getEdgeView(ed).setControlPoint(ctr_x, ctr_y);
            }
        }
        
        initMouseEvent();
        setTitle(file_ch.getSelectedFile().getCanonicalPath());
        postMessage("File " + file_ch.getSelectedFile().getName() + " opened.");
        repaint();
    }
    
    /**
     * Monta e retorna uma representação XML do
     * grafo atual desta janela.
     * @throws java.lang.Exception
     */
    public String getXMLGraph() throws Exception {
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = db.newDocument();
        
        doc.appendChild(doc.createComment("GraphXT - v0.1"));
        
        Element graph = doc.createElement("graph");
        doc.appendChild(graph);
        
        for (VertexView<String> v : graph_view.getVertexViewSet()) {
            Element vert = doc.createElement("vertex");
            
            vert.setAttribute("data", v.getVertex().getData());
            vert.setAttribute("x", String.valueOf(v.getX()));
            vert.setAttribute("y", String.valueOf(v.getY()));
            vert.setAttribute("selected",(v.isSelected() ? "1" : "0"));
            
            graph.appendChild(vert);
        }
        
        for (EdgeView<String,Integer> ed : graph_view.getEdgeViewSet()) {
            Element edge = doc.createElement("edge");
            
            edge.setAttribute("start", ed.getStartVertexView().getVertex().getData());
            edge.setAttribute("end", ed.getEndVertexView().getVertex().getData());
            edge.setAttribute("data", ed.getEdge().getData().toString());
            edge.setAttribute("control_x", String.valueOf(ed.getControlX()));
            edge.setAttribute("control_y", String.valueOf(ed.getControlY()));
            edge.setAttribute("selected", (ed.isSelected() ? "1" : "0"));
            edge.setAttribute("directed", (ed.getEdge().isDirected() ? "1" : "0"));
            
            graph.appendChild(edge);
        }

        Transformer trans = TransformerFactory.newInstance().newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(doc);
        trans.transform(source, result);
        
        return sw.toString();
    }
    
    private Timer timer;
    private GraphView graph_view;
    private GraphTheme theme;
    private DefaultListModel messages;
    private ArrayList<JToggleButton> toggle_buttons;
    private final JFileChooser file_ch;
    
  // Variables declaration - do not modify//GEN-BEGIN:variables
  public javax.swing.JToggleButton adEdButton;
  public javax.swing.JToggleButton adVeButton;
  private javax.swing.JRadioButton bfsOpt;
  private javax.swing.ButtonGroup buttonGroup1;
  private javax.swing.JButton clearButton;
  private javax.swing.JRadioButton dfsOpt;
  private javax.swing.JRadioButton dijOpt;
  private javax.swing.JRadioButton fordFulkerson;
  private javax.swing.JButton jButton1;
  private javax.swing.JButton jButton2;
  private javax.swing.JButton jButton3;
  private javax.swing.JButton jButton4;
  private javax.swing.JButton jButton5;
  private javax.swing.JButton jButton6;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JPanel jPanel10;
  private javax.swing.JPanel jPanel2;
  private javax.swing.JPanel jPanel3;
  private javax.swing.JPanel jPanel4;
  private javax.swing.JPanel jPanel5;
  private javax.swing.JPanel jPanel6;
  private javax.swing.JPanel jPanel7;
  private javax.swing.JPanel jPanel8;
  private javax.swing.JPanel jPanel9;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JScrollPane jScrollPane2;
  private javax.swing.JToolBar.Separator jSeparator1;
  private javax.swing.JToolBar.Separator jSeparator2;
  private javax.swing.JToolBar.Separator jSeparator3;
  private javax.swing.JTabbedPane jTabbedPane1;
  private javax.swing.JTabbedPane jTabbedPane2;
  private javax.swing.JToolBar jToolBar1;
  private javax.swing.JRadioButton kruskalOpt;
  public javax.swing.JToggleButton lbEdButton;
  public javax.swing.JToggleButton lbVeButton;
  private javax.swing.JList messageBoard;
  private javax.swing.JRadioButton primOpt;
  public javax.swing.JToggleButton reEdButton;
  public javax.swing.JToggleButton reVeButton;
  public javax.swing.JToggleButton selEdButton;
  public javax.swing.JToggleButton selVeButton;
  public javax.swing.JToggleButton selVeEdButton;
  private javax.swing.JSlider speedSlider;
  private javax.swing.JRadioButton topOpt;
  // End of variables declaration//GEN-END:variables
    
}
